home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / misc / memtest8.000 / memtest8 / memtest86 / mtest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-29  |  7.2 KB  |  394 lines

  1. /* mtest.c - MemTest-86 */
  2.  
  3. /* Copyright 1996,  Chris Brady
  4.  *
  5.  * Permission to use, copy, modify, and distribute this
  6.  * software and its documentation for any purpose and without fee
  7.  * is granted provided that the above copyright notice appears in all copies.
  8.  * It is provided "as is" without express or implied warranty.
  9.  */
  10.  
  11. #include <linux/tty.h>
  12. #include <linux/sched.h>
  13. #include <asm/io.h>
  14. #include "mtest.h"
  15.  
  16. unsigned short memsz;
  17.  
  18. extern __inline__ void cache_off()
  19. {
  20.         __asm__("push %eax\n\t"
  21.         "movl %cr0,%eax\n\t"
  22.                 "orl $0x60000000,%eax\n\t"
  23.                 "movl %eax,%cr0\n\t"
  24.         ".byte 0x0f,0x08\n\t"
  25.         "pop  %eax\n\t");
  26. }
  27. extern __inline__ void cache_on()
  28. {
  29.         __asm__("push %eax\n\t"
  30.         "movl %cr0,%eax\n\t"
  31.                 "andl $0x9fffffff,%eax\n\t"
  32.                 "movl %eax,%cr0\n\t"
  33.         "pop  %eax\n\t");
  34. }
  35.  
  36. struct segs {
  37.     long *start;
  38.     long *end;
  39. } seg[10];
  40.  
  41. long *start;
  42. long *end;
  43. long p1, p2;
  44. char buf[12];
  45. int pass = 0;
  46. int ecount = 0;
  47. int segs, p0, emsg = 0;
  48. long *eadr, exor;
  49. long *p;
  50. char *pp;
  51. int i, cache_flag, ref_flag;
  52. long m_lim;
  53.  
  54. char spin[] = {'/', '-', '\\', '|'};
  55.  
  56. asmlinkage void do_test(void)
  57. {
  58.     /*
  59.      * Make a spiffy title on a blue background
  60.      */
  61.     for(i=0, pp=(char *)0xb8001; i<17; i++, pp+=2) {
  62.         *pp = 0x017;
  63.     }
  64.     cprint(0, 0, " MEMTEST-86 v1.1 ");
  65.     cprint(0, 31, "MemSz-BIOS:");
  66.     dprint(0, 45, memsz+1024, 5);
  67.     cprint(0, 50, "k");
  68.     
  69.     /*
  70.      * Find all segments of RAM
  71.      *
  72.      * We test for DRAM by reading a location and then writing  the
  73.      * complement. If any bits change then we assume that it is DRAM.
  74.      * To save time we only do this check every 64 bytes.
  75.      */
  76.     cprint(2, 0, "Testing: ");
  77.  
  78.     i = 0;
  79.     m_lim = (memsz * 1024) + (1024 * 1024);
  80.     p = (long *)START_ADR;
  81.     seg[i].start = p;
  82.     dprint(2, 9, (long)p/1024, 5);
  83.     cprint(2, 14, "k - ");
  84.     while ((long)p < m_lim) {
  85.         /*
  86.          * Skip over the display memory
  87.          */
  88.         if (((long)p & 0xfffff000) == 0xb8000) {
  89.             seg[i].end = p;
  90.             dprint(2+i, 18, (long)p/1024, 5);
  91.             cprint(2+i, 23, "k");
  92.             p = (long *)0xc0000;
  93.             i++;
  94.             seg[i].start = 0;
  95.             goto fstart;
  96.         }
  97.         p1 = *p;
  98.         *p = ~p1;
  99.         if (*p == p1) {
  100.             /*
  101.              * ROM or nothing at this address, record end addrs
  102.              */
  103.             seg[i].end = p;
  104.             dprint(2 + i, 18, (long)p/1024, 5);
  105.             cprint(2 + i, 23, "k");
  106.             i++;
  107.             seg[i].start = 0;
  108. fstart:
  109.             while ((long)p < m_lim) {
  110.                 /*
  111.                  * Skip over video memory
  112.                  */
  113.                 if (((long)p & 0xfffff000) == 0xb8000) {
  114.                     p = (long *)0xc0000;
  115.                 }
  116.                 p1 = *p;
  117.                 *p =  ~p1;
  118.                 if (*p != p1) {
  119.                     /*
  120.                      * More RAM, record start addrs
  121.                      */
  122.                     seg[i].start = p;
  123.                     dprint(2 + i, 9, (long)p/1024, 5);
  124.                     cprint(2 + i, 14, "k - ");
  125.                     break;
  126.                 }
  127.                 p += 64;
  128.             }
  129.         }
  130.         p += 64;
  131.     }
  132.     if (seg[i].start) {
  133.         seg[i].end = p;
  134.         dprint(2 + i, 18, (long)p/1024, 5);
  135.         cprint(2 + i, 23, "k");
  136.         i++;
  137.         seg[i].start = 0;
  138.     }
  139.     segs = i;
  140.  
  141.     cprint(1, 34, "Pattern:");
  142.     cprint(2, 34, "Refresh:");
  143.     cprint(2, 43, " Default");
  144.     cprint(0, 63, "  Pass:");
  145.     dprint(0, 71, pass, 5);
  146.     cprint(1, 63, "Errors:");
  147.     dprint(1, 71, ecount, 5);
  148.     cprint(2, 63, " Cache:");
  149.     cprint(2, 73, " ON");
  150.  
  151.  
  152.     /*
  153.      * Main Loop
  154.      */
  155.     while (1) {
  156. #ifdef CACHE
  157.         /*
  158.          * Alternate cache on and off for each pass
  159.          */
  160.         if (cache_flag) {
  161.             cache_flag = 0;
  162.             cprint(2, 73, "OFF");
  163.             cache_off();
  164.         } else {
  165.             cache_flag++;
  166.             cprint(2, 73, " ON");
  167.             cache_on();
  168. #endif
  169. #ifdef REFRESH
  170.             /*
  171.              * For every 2 passes alternate with short and long
  172.              * refresh rates
  173.              */
  174.             if (ref_flag) {
  175.                 ref_flag = 0;
  176.                 /* set refresh to 150ms */
  177.                 outb(0x74, 0x43);
  178.                 outb(0xb4, 0x41);
  179.                 outb(0x00, 0x41);
  180.                 cprint(2, 43, "Extended (150ms)");
  181.             } else {
  182.                 ref_flag++;
  183.                 /* set refresh to 15ms */
  184.                 outb(0x74, 0x43);
  185.                 outb(0x12, 0x41);
  186.                 outb(0x00, 0x41);
  187.                 cprint(2, 43, "  Normal (15ms) ");
  188.             }
  189. #endif
  190. #ifdef CACHE
  191.         }
  192. #endif
  193.         /*
  194.          * Use a 4 bit wide walking ones pattern and it's complement.
  195.          * This will check out 4 bit wide chips.  This should be
  196.          * changed if chips more than 4 bits wide become available.
  197.          */
  198.         p0 = 8;
  199.         for (i=0; i<5; i++, p0=p0>>1) {
  200.             p1 = p0 | (p0<<4) | (p0<<8) | (p0<<12) | (p0<<16) |
  201.                 (p0<<20) | (p0<<24) | (p0<<28);
  202.             p2 = ~p1;
  203.             check();
  204.         
  205.             /*
  206.              * Switch patterns
  207.              */
  208.             p2 = p1;
  209.             p1 = ~p2;
  210.             check();
  211.         }
  212.         dprint(0, 71, ++pass, 5);
  213.     }
  214. }
  215.  
  216. /*
  217.  * Test all of memory using a "moving inversions" algorithm using the
  218.  * pattern in p1 and it's complement in p2.
  219.  */
  220. check()
  221. {
  222.     register int i, j;
  223.     register long *p;
  224.     char *s = spin;
  225.  
  226.         hprint(1, 43, p1);
  227.  
  228.     /*
  229.      * Initialize memory with the initial pattern.
  230.      */
  231.     for (j=0; j<segs; j++) {
  232.         start = seg[j].start;
  233.         end = seg[j].end;
  234.         for (p = start; p < end; p++) {
  235.             *p = p1;
  236.         }
  237.     }
  238.     /*
  239.      * Do moving inversions test. Check for initial pattern and then
  240.      * write the complement for each memory location. Test from bottom
  241.      * up and then from the top down.
  242.      */
  243.     for (i=0; i<3; i++) {
  244.         for (j=0; j<segs; j++) {
  245.             start = seg[j].start;
  246.             end = seg[j].end;
  247.             for (p = start; p < end; p++) {
  248.                 if (*p != p1) {
  249.                     error(p, p1, *p);
  250.                 }
  251.                 *p = p2;
  252.             }
  253.         }
  254.         do_spin();
  255.         for (j=segs-1; j>=0; j--) {
  256.             start = seg[j].start;
  257.             end = seg[j].end;
  258.             for (p = end - 1; p >= start; p--) {
  259.                 if (*p != p2) {
  260.                     error(p, p2, *p);
  261.                 }
  262.                 *p = p1;
  263.             }
  264.         }
  265.         do_spin();
  266.     }
  267. }
  268.  
  269. /*
  270.  * Display data error message. Don't display repeat duplicate errors.
  271.  */
  272. error(adr, good, bad)
  273. long *adr;
  274. long good;
  275. long bad;
  276. {
  277.     long xor;
  278.  
  279.     xor = good ^ bad;
  280.     if (emsg < 23-segs && (adr != eadr || xor != exor)) {
  281.         cprint(emsg+segs+3, 0, "Data Error - Addrs: ");
  282.         hprint(emsg+segs+3, 20, adr);
  283.         cprint(emsg+segs+3, 30, "Good: ");
  284.         hprint(emsg+segs+3, 36, good);
  285.         cprint(emsg+segs+3, 46, "Bad: ");
  286.         hprint(emsg+segs+3, 51, bad);
  287.         cprint(emsg+segs+3, 61, "Xor: ");
  288.         hprint(emsg+segs+3, 66, xor);
  289.         eadr = adr;
  290.         exor = xor;
  291.         emsg++;
  292.     }
  293.     dprint(1, 71, ++ecount, 5);
  294. }
  295.  
  296. /*
  297.  * Print characters on screen
  298.  */
  299. cprint(y, x, text)
  300. int y;
  301. int x;
  302. char *text;
  303. {
  304.     register int i;
  305.     char *dptr;
  306.  
  307.     dptr = (char *)(0xb8000 + (160*y) + (2*x));
  308.     for (i=0; i < text[i]; i++) {
  309.         *dptr = text[i];
  310.         dptr += 2;
  311.     }
  312. }
  313.  
  314. /*
  315.  * Print a decimal number on screen
  316.  */
  317. dprint(x, y, val, len)
  318. int x;
  319. int y;
  320. long val;
  321. int len;
  322. {
  323.         long j, k;
  324.         int i, flag=0;
  325.         char c;
  326.  
  327.         for(i=0, j=1; i<len-1; i++) {
  328.                 j *= 10;
  329.         }
  330.         for (i=0; j>0; j/=10) {
  331.                 k = val/j;
  332.                 if (k > 9) {
  333.                         j *= 100;
  334.                         continue;
  335.                 }
  336.                 if (flag || k || j == 1) {
  337.                         buf[i++] = k + '0';
  338.             flag++;
  339.                 } else {
  340.             buf[i++] = ' ';
  341.         }
  342.                 val -= k * j;
  343.         }
  344.         buf[i] = 0;
  345.     cprint(x, y, buf);
  346. }
  347.  
  348. /*
  349.  * Print a hex number on screen
  350.  */
  351. hprint(x, y, val)
  352. int x;
  353. int y;
  354. long val;
  355. {
  356.     long j;
  357.     int i, idx, flag = 0;
  358.     char c;
  359.  
  360.         for (i=0, idx=0; i<8; i++) {
  361.                 j = val >> (28 - (4 * i));
  362.         j &= 0xf;
  363.         if (j < 10) {
  364.             if (flag || j || i == 7) {
  365.                         buf[idx++] = j + '0';
  366.                 flag++;
  367.             } else {
  368.                 buf[idx++] = ' ';
  369.             }
  370.         } else {
  371.             buf[idx++] = j + 'a' - 10;
  372.             flag++;
  373.         }
  374.         }
  375.         buf[idx] = 0;
  376.     cprint(x, y, buf);
  377. }
  378.     
  379. /*
  380.  * Display a spinning pattern to show progress
  381.  */
  382. do_spin()
  383. {
  384.     static int s=0;
  385.     char *dptr = (char *)0xb8024;
  386.  
  387.     *dptr = spin[s]&0x7f;
  388.     dptr++;
  389.     *dptr = 0xf;
  390.     if (++s > 3) {
  391.         s = 0;
  392.     }
  393. }
  394.